using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using HybridCLR;

public class Loader : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(LoadAndStart());
    }

    private IEnumerator LoadAndStart()
    {
        Debug.Log("Starting to load assemblies...");

        // Load AOT metadata assemblies
        string aotMetadataDir = $"{Application.streamingAssetsPath}/AotMetadata";
        List<string> aotMetaAssemblyFiles = new List<string>
        {
            "mscorlib.dll", "System.dll", "System.Core.dll",
            "UnityEngine.CoreModule.dll", "UnityEngine.AssetBundleModule.dll",
            "UnityEngine.UI.dll", "Unity.InputSystem.dll"
        };
        foreach (var assemblyName in aotMetaAssemblyFiles)
        {
            string dllPath = $"{aotMetadataDir}/{assemblyName}.bytes";
            byte[] dllBytes = null;
            yield return StartCoroutine(ReadBytesFromStreamingAssets(dllPath, bytes => dllBytes = bytes));
            if (dllBytes != null)
            {
                var err = RuntimeApi.LoadMetadataForAOTAssembly(dllBytes, HomologousImageMode.Consistent);
                Debug.Log($"Loaded AOT metadata for {assemblyName}, result: {err}");
            }
        }

        // Load hot-update assemblies
#if UNITY_EDITOR
        // In the editor, load hot-update assemblies from local files for fast iteration.
        string hotUpdateDllPath = $"{Application.streamingAssetsPath}/HotUpdateDlls/HotUpdate.dll.bytes";
        byte[] hotUpdateDllBytes = null;
        yield return StartCoroutine(ReadBytesFromStreamingAssets(hotUpdateDllPath, bytes => hotUpdateDllBytes = bytes));
        if (hotUpdateDllBytes != null)
        {
            Assembly.Load(hotUpdateDllBytes);
            Debug.Log("Successfully loaded local HotUpdate.dll.");
        }
#else
        // In a build, download hot-update assemblies from the server.
        string hotUpdateUrl = "https://download.nineland.cn/test/addressables/ServerData/HotUpdate.dll.bytes";
        Debug.Log($"Downloading hot-update DLL from: {hotUpdateUrl}");

        using (UnityWebRequest www = UnityWebRequest.Get(hotUpdateUrl))
        {
            yield return www.SendWebRequest();

            if (www.result == UnityWebRequest.Result.Success)
            {
                byte[] hotUpdateDllBytes = www.downloadHandler.data;
                Assembly.Load(hotUpdateDllBytes);
                Debug.Log("Successfully downloaded and loaded HotUpdate.dll.");
            }
            else
            {
                Debug.LogError($"Failed to download hot-update DLL. Error: {www.error}");
            }
        }
#endif

        Debug.Log("All assemblies loaded, switching to PlayerCubeScene.");
        SceneManager.LoadScene("PlayerCubeScene");
    }

    // Coroutine to read bytes from StreamingAssets, which works on all platforms.
    private IEnumerator ReadBytesFromStreamingAssets(string path, System.Action<byte[]> callback)
    {
        string url = path;
        // In the Unity Editor on Windows, paths from Application.streamingAssetsPath
        // start with a drive letter (e.g., "C:/...") which UnityWebRequest
        // can misinterpret as a protocol. Prepending "file://" ensures it's
        // correctly treated as a local file path. This is generally safe for other
        // editor platforms as well. For device builds, Application.streamingAssetsPath
        // is usually a URL-friendly path already.
#if UNITY_EDITOR
        url = "file://" + path;
#endif
        UnityWebRequest www = UnityWebRequest.Get(url);
        yield return www.SendWebRequest();

        if (www.result == UnityWebRequest.Result.Success)
        {
            callback(www.downloadHandler.data);
        }
        else
        {
            Debug.LogError($"Failed to load file with UnityWebRequest: {url}, Error: {www.error}");
            callback(null);
        }
    }
} 